#include "Mesh.h"

#include "Log.h"

Mesh::Mesh(LPDIRECT3DDEVICE9 g_d3dDevice, const char *fileName)
{
	LPD3DXBUFFER pD3DXMtrlBuffer;
	m_mesh				= NULL; // Our mesh object in sysmem
	m_meshMaterials		= NULL; // Materials for our mesh
	m_meshTextures		= NULL; // Textures for our mesh
	m_dwNumMaterials	= 0L;   // Number of mesh materials


    //Load the mesh from the specified file
    if(FAILED(D3DXLoadMeshFromX(fileName, D3DXMESH_SYSTEMMEM,
                                g_d3dDevice, NULL,
                                &pD3DXMtrlBuffer, NULL, &m_dwNumMaterials,
                                &m_mesh)))
    {
        //If model is not in current folder, try parent folder
        if(FAILED(D3DXLoadMeshFromX(fileName, D3DXMESH_SYSTEMMEM,
                                    g_d3dDevice, NULL,
                                    &pD3DXMtrlBuffer, NULL, &m_dwNumMaterials,
                                    &m_mesh)))
        {
            Log("	WARNING: Unable to find mesh");
        }
    }

	//We need to extract the material properties and texture names from the 
    //pD3DXMtrlBuffer
    D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
    m_meshMaterials = new D3DMATERIAL9[m_dwNumMaterials];
    m_meshTextures = new LPDIRECT3DTEXTURE9[m_dwNumMaterials];

    for(DWORD i = 0; i < m_dwNumMaterials; i++)
    {
        //Copy the material
        m_meshMaterials[i] = d3dxMaterials[i].MatD3D;

        //Set the ambient color for the material (D3DX does not do this)
        m_meshMaterials[i].Ambient = m_meshMaterials[i].Diffuse;

        m_meshTextures[i] = NULL;
        if(d3dxMaterials[i].pTextureFilename != NULL &&
           lstrlenA(d3dxMaterials[i].pTextureFilename) > 0)
        {
            // Create the texture
            if(FAILED(D3DXCreateTextureFromFileA(g_d3dDevice,
                                                 d3dxMaterials[i].pTextureFilename,
                                                 &m_meshTextures[i] ) ) )
            {
                //If texture is not in current folder, try parent folder
                const CHAR* strPrefix = "..\\";
                CHAR strTexture[MAX_PATH];
                strcpy_s(strTexture, MAX_PATH, strPrefix);
                strcat_s(strTexture, MAX_PATH, d3dxMaterials[i].pTextureFilename);
                //If texture is not in current folder, try parent folder
                if(FAILED(D3DXCreateTextureFromFileA(g_d3dDevice,
                                                     strTexture,
                                                     &m_meshTextures[i])))
                {
                    Log("	WARNING: Unable to find texture");
                }
            }
        }
    }

    //Done with the material buffer
    pD3DXMtrlBuffer->Release();
}

Mesh::~Mesh()
{
	if(m_meshMaterials != NULL)
        delete[] m_meshMaterials;

    if(m_meshTextures)
    {
        for(DWORD i = 0; i < m_dwNumMaterials; i++)
        {
            if(m_meshTextures[i])
                m_meshTextures[i]->Release();
        }
        delete[] m_meshTextures;
    }
    if(m_mesh != NULL)
        m_mesh->Release();
	delete m_mesh;
}

void Mesh::Render(LPDIRECT3DDEVICE9 g_d3dDevice)
{
	for(DWORD i = 0; i < m_dwNumMaterials; i++)
	{
		m_mesh->DrawSubset(i);
	}
}